﻿using BlogsAPI.Properties;

namespace RssToolkit.Xml
{
    using System;
    using System.IO;
    using System.Xml;
    using System.Xml.Serialization;
    using System.Diagnostics.CodeAnalysis;

    /// <summary>
    /// Abstract class for RSS Document
    /// </summary>
    public abstract class XmlDocumentBase
    {
        /// <summary>
        /// Gets or sets the version.
        /// </summary>
        /// <value>The version.</value>
        [XmlAttribute("version")]
        public string Version { get; set; }

        /// <summary>
        /// Gets or sets the URL.
        /// </summary>
        /// <value>The URL.</value>
        internal string Url { get; set; }

        /// <summary>
        /// Returns Xml in the type specified by outputType
        /// </summary>
        /// <param name="outputType">Type of the output.</param>
        /// <returns></returns>
        public virtual string ToXml(DocumentType outputType)
        {
            return string.Empty;
        }

        /// <summary>
        /// string XML representation.
        /// </summary>
        /// <returns>string</returns>
        protected static string ToXml<T>(DocumentType outputType, T oDocument) where T : XmlDocumentBase
        {
            string sXml = XmlHelper.ToXml(oDocument);

            return XmlHelper.ConvertTo(outputType, sXml);
        }

        /// <summary>
        /// Loads the specified URL.
        /// </summary>
        /// <param name="url">The URL.</param>
        /// <returns>RssDocument</returns>
        [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#"),
        SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
        protected static T Load<T>(Uri url, Boolean useCache) where T : XmlDocumentBase
        {
            if (url == null)
            {
                throw new ArgumentNullException("url");
            }
            // resolve app-relative URLs
            string xmlUrl = XmlHelper.ResolveAppRelativeLinkToUrl(url.OriginalString);

            // download the feed
            using (Stream cachedXml = DownloadManager.GetFeed(xmlUrl, useCache))
            {
                using (XmlTextReader reader = new XmlTextReader(cachedXml))
                {
                    T rss = Load<T>(reader);

                    //// remember the url
                    rss.Url = xmlUrl;

                    return rss;
                }
            }
        }

        /// <summary>
        /// Loads the specified reader.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <returns>Generic Type of RssDocumentBase</returns>
        [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
        protected static T Load<T>(XmlReader reader) where T : XmlDocumentBase
        {
            T xml = null;
            string sXml = XmlHelper.ConvertToXml(reader);

            if (!string.IsNullOrEmpty(sXml))
            {
                xml = LoadFromRssXml<T>(sXml);
            }

            return xml;
        }

        /// <summary>
        /// Loads from XML.
        /// </summary>
        /// <param name="xml">The XML.</param>
        /// <returns>Generic Type of RssDocumentBase</returns>
        [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
        protected static T Load<T>(string xml) where T : XmlDocumentBase
        {
            T xmlDocument;
            using (StringReader stringReader = new StringReader(xml))
            {
                using (XmlTextReader reader = new XmlTextReader(stringReader))
                {
                    xmlDocument = Load<T>(reader);
                }
            }

            return xmlDocument;
        }

        private static T LoadFromRssXml<T>(string rssXml) where T : XmlDocumentBase
        {
            if (string.IsNullOrEmpty(rssXml))
            {
                throw new ArgumentException(string.Format(Resources.Culture, Resources.ArgmentException, "xml"));
            }

            T xml = XmlHelper.DeserializeFromXmlUsingStringReader<T>(rssXml);

            return xml;
        }
    }
}
